﻿using AutoMapper;
using CarparkBusiness;
using CarparkIMS_CMS.Extensions;
using CarparkIMS_CMS.Infrastructure;
using CarparkIMS_CMS.Infrastructure.Mapper;
using CarparkIMS_CMS.SignalR;
using CarparkIMS_Model;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace CarparkIMS_CMS
{
    public class Startup
    {
        public const string AuthSchemes = CookieAuthenticationDefaults.AuthenticationScheme;
        public Startup(IConfiguration configuration, IWebHostEnvironment hostingEnvironment)
        {
            Configuration = configuration;
            _hostingEnvironment = hostingEnvironment;
        }

        public IConfiguration Configuration { get; }
        private readonly IWebHostEnvironment _hostingEnvironment;

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            string connStr = Configuration.GetConnectionString("IMSDatabase");
            services.AddDbContextPool<IMSContext>(options => options.UseSqlServer(connStr));
            //System.IO.File.WriteAllText("d:\\dbConnTEXTvalid.txt", connStr);

            //create default file provider
            CommonHelper.DefaultFileProvider = new NopFileProvider(_hostingEnvironment);

            //register mapper configurations
            var typeFinder = new WebAppTypeFinder();
            AddAutoMapper(services, typeFinder);

            services.AddMvc().AddRazorRuntimeCompilation(); //buyonggengxinyemian
            services.AddControllersWithViews();
            services.AddSignalR();
            //class service
            services.AddScoped<IBackgroundServiceStatus, BackgroundServiceStatus>();

            //Jwt Or Cookie Authentication ---------------------------------------------------------------------------------
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.ReturnUrlParameter = "returnUrl";
                options.Cookie.Name = "ConnectToken";
                options.LoginPath = new PathString($"/Account/Login");
                options.LogoutPath = new PathString($"/Account/Logout");
                options.AccessDeniedPath = new PathString($"/Account/AccessDenied");
                options.SlidingExpiration = true;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(1440);
            });

            services.AddHostedService<TimedHostedService>();
            services.AddScoped<IScopedService, ScopedService>();

            services.AddHttpContextAccessor();
            services.Configure<ParkingSettingX>(Configuration.GetSection("ParkingSetting"));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            string rootPath = env.ContentRootPath;
            string logPath = Path.Combine(rootPath, "log");
            if (!Directory.Exists(logPath))
            {
                Directory.CreateDirectory(logPath);
            }
            string logPathFile = Path.Combine(logPath, "Logging.log");

            loggerFactory.AddFile(logPathFile, fileSizeLimitBytes: 2000000);

            app.UseHsts();

            app.UseHttpsRedirection();

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=PlateRegistration}/{action=Index}/{id?}");
                endpoints.MapHub<NotiHub>("/noti");
            });
        }

        protected virtual void AddAutoMapper(IServiceCollection services, ITypeFinder typeFinder)
        {
            //find mapper configurations provided by other assemblies
            var mapperConfigurations = typeFinder.FindClassesOfType<IOrderedMapperProfile>();

            //create and sort instances of mapper configurations
            var instances = mapperConfigurations
                .Select(mapperConfiguration => (IOrderedMapperProfile)Activator.CreateInstance(mapperConfiguration))
                .OrderBy(mapperConfiguration => mapperConfiguration.Order);

            //create AutoMapper configuration
            var config = new MapperConfiguration(cfg =>
            {
                foreach (var instance in instances)
                {
                    cfg.AddProfile(instance.GetType());
                }
            });

            //register
            AutoMapperConfiguration.Init(config);
        }
    }
}
